/*
 *    Copyright (c) 2018-2025, proj All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the proj developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: proj
 */
package com.ykht.proj.coupon.service.impl;

import cn.hutool.core.bean.BeanUtil;

import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codingapi.tx.annotation.TxTransaction;
import com.ykht.proj.admin.api.Enum.UserRoleTypeEnum;
import com.ykht.proj.admin.api.dto.UserDTO;
import com.ykht.proj.admin.api.entity.SysUser;
import com.ykht.proj.admin.api.feign.RemoteFileService;
import com.ykht.proj.admin.api.feign.RemoteUserService;
import com.ykht.proj.common.core.constant.CommonConstants;
import com.ykht.proj.common.core.util.R;
import com.ykht.proj.common.security.util.SecurityUtils;
import com.ykht.proj.coupon.Enum.MerchantTypeEnum;
import com.ykht.proj.coupon.Enum.UserTypeEnum;
import com.ykht.proj.coupon.entity.*;
import com.ykht.proj.coupon.mapper.*;
import com.ykht.proj.coupon.service.*;
import com.ykht.proj.coupon.vo.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 品牌表
 *
 * @author proj code generator
 * @date 2020-11-16 17:00:21
 */
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy, @Autowired})
@Slf4j
@Transactional
@SuppressWarnings("all")
public class CnBrandServiceImpl extends ServiceImpl<CnBrandMapper, CnBrand> implements CnBrandService {

	private final CnBraLabService cnBraLabService;

	private final CnBrandMapper cnBrandMapper;
	private final RemoteFileService fileService;
	private final CnCouponService cnCouponService;
	private final CnCouShopService cnCouShopService;
	private final CnCareMapper cnCareMapper;
	private final CnShopMapper cnShopMapper;
	private final CnCompanyMapper cnCompanyMapper;
	private final RemoteUserService remoteUserService;
	private final FxConfBrandPersonService fxConfBrandPersonService;
	private final FxMerchantAccountService fxMerchantAccountService;

	@Value("${oss.baseHost}")
	private String ossBaseHost;

	@TxTransaction(isStart = true) // 请求方 要加 isStart = true  被请求的不用加  isStart = true  控制事物 注解
	@Transactional(rollbackFor = Exception.class)
	@Override
	public R insertBrand(CnBrandVo cnBrandVo) throws Exception {
		CnBrand brand = new CnBrand().selectOne(Wrappers.lambdaQuery(CnBrand.class)
				.eq(CnBrand::getBrandName, cnBrandVo.getBrandName()));
		if (brand != null) {
			return R.ok("品牌名称已经存在");
		}
		if (cnBrandVo.getDisplay().equals(0)) {
			if (cnBrandVo.getContractStartTime().isAfter(LocalDateTime.now()) || cnBrandVo.getContractEndTime().isBefore(LocalDateTime.now())) {
				return R.failed("当前时间不在该品牌合作时间内，不能上架");
			}
			cnBrandVo.setOnTime(LocalDateTime.now());
		} else {
			cnBrandVo.setOffTime(LocalDateTime.now());
		}

		cnBrandVo.setCreateUser(SecurityUtils.getUserId());
		cnBrandVo.setCreateTime(LocalDateTime.now());
		cnBrandVo.setUserType(UserTypeEnum.brand.getValue());
		CnBrand cnBrand = BeanUtil.toBean(cnBrandVo, CnBrand.class);
		cnBrandMapper.insert(cnBrand);
		cnBrandVo.setId(cnBrand.getId());
		if (cnBrand.getLoginId() != null) {
			SysUser user = new SysUser();
			user.setUserId(Integer.parseInt(cnBrand.getLoginId().toString()));
			user.setSjIdDefLogin(cnBrand.getId());
			remoteUserService.bindSj(user);
		}
		if (cnBrand.getLoginId() == null) {
			UserDTO userDTO = new UserDTO();
			userDTO.setUsername(StringUtils.isEmpty(cnBrandVo.getUsername()) ? cnBrandVo.getBrandName() : cnBrandVo.getUsername());
			userDTO.setUserType(UserTypeEnum.brand.getValue());
			userDTO.setPassword("123456");
			userDTO.setParentId(cnBrandVo.getParentId());
			userDTO.setRole(UserRoleTypeEnum.brand.getValue());
			userDTO.setSjIdDefLogin(cnBrand.getId());
			R<UserDTO> userDTOR = remoteUserService.saveUser(userDTO);
			if (userDTOR.getCode() != 0) {
				throw new RuntimeException(userDTOR.getMsg());
			}
			cnBrand.setLoginId(Long.valueOf(userDTOR.getData().getUserId()));
			this.updateById(cnBrand);
		}
		saveCnbarLab(cnBrand.getId(), cnBrandVo);
		//添加账户信息
		FxMerchantAccount account = fxMerchantAccountService.cheeckOrCreateAccont(MerchantTypeEnum.brand.getValue(), cnBrand.getId());
		return R.ok(cnBrandVo);
	}

	@TxTransaction(isStart = true) // 请求方 要加 isStart = true  被请求的不用加  isStart = true  控制事物 注解
	@Transactional(rollbackFor = Exception.class)
	@Override
	public R updateBrand(CnBrandVo cnBrandVo) throws Exception {
		CnBrand brand = new CnBrand().selectOne(Wrappers.lambdaQuery(CnBrand.class)
				.eq(CnBrand::getBrandName, cnBrandVo.getBrandName())
				.ne(CnBrand::getId, cnBrandVo.getId()));
		if (brand != null) {
			return R.ok("品牌名称已经存在");
		}
		cnBrandVo.setUpdateTime(LocalDateTime.now());
		cnBrandVo.setUpdateUser(SecurityUtils.getUserId());
		cnBrandVo.setUserType(UserTypeEnum.brand.getValue());
		if (cnBrandVo.getLoginId() != null) {
			SysUser user = new SysUser();
			user.setUserId(Integer.parseInt(cnBrandVo.getLoginId().toString()));
			user.setSjIdDefLogin(cnBrandVo.getId());
			remoteUserService.bindSj(user);
		}

		if (null != cnBrandVo.getUsername()) {
			UserDTO userDTO = new UserDTO();
			userDTO.setUsername(cnBrandVo.getUsername());
			userDTO.setUserType(UserTypeEnum.brand.getValue());
			userDTO.setPassword("123456");
			userDTO.setParentId(cnBrandVo.getParentId());
			userDTO.setRole(UserRoleTypeEnum.brand.getValue());
			userDTO.setSjIdDefLogin(cnBrandVo.getId());
			R<UserDTO> userDTOR = remoteUserService.saveUser(userDTO);
			if (userDTOR.getCode() != 0) {
				throw new RuntimeException(userDTOR.getMsg());
			}
			cnBrandVo.setLoginId(Long.valueOf(userDTOR.getData().getUserId()));
		}
		CnBrand cnBrand = BeanUtil.toBean(cnBrandVo, CnBrand.class);
		this.updateById(cnBrand);
		QueryWrapper<CnBraLab> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(CnBraLab::getBrandId, cnBrand.getId());
		cnBraLabService.remove(queryWrapper);
		saveCnbarLab(cnBrand.getId(), cnBrandVo);
		return R.ok(cnBrandVo);
	}

	private void saveCnbarLab(Long brandId, CnBrandVo cnBrandVo) {
		List<CnBraLab> list = new ArrayList<>();
		List<Long> labelIds = cnBrandVo.getLabelIds();
		labelIds.forEach(labId -> {
			CnBraLab cnBraLab = new CnBraLab();
			cnBraLab.setBrandId(brandId);
			cnBraLab.setLabelId(labId);
			cnBraLab.setCreateTime(LocalDateTime.now());
			cnBraLab.setCreateUser(SecurityUtils.getUserId());
			list.add(cnBraLab);
		});
		cnBraLabService.saveBatch(list);
	}

	@Override
	public R queryPage(Page page, CnBrandVo cnBrandVo) {
		Integer userType = SecurityUtils.getUser().getUserType();
		Long userId = SecurityUtils.getUserId();
		if (userType.equals(UserTypeEnum.company.getValue())) {
			cnBrandVo.setCompanyId(SecurityUtils.getSjId());
		}
		if (userType.equals(UserTypeEnum.brand.getValue())) {
			cnBrandVo.setLoginId(SecurityUtils.getSjId());
		}
		List<CnBrandVo> list = cnBrandMapper.queryPage(page, cnBrandVo);
		if (list != null && list.size() > 0) {
			List<Long> loginList = new ArrayList<>();
			for (CnBrandVo vo : list) {
				List<Long> ids = new ArrayList<>();
				if (vo.getLabelId() != null) {
					for (String id : vo.getLabelId().split(",")) {
						ids.add(Long.valueOf(id));
					}
				}
				vo.setLabelIds(ids);
				loginList.add(vo.getLoginId());
			}
			List<SysUser> userList = remoteUserService.userByIds(loginList);
			list.stream().forEach(itme -> {
				userList.stream().forEach(user -> {
					if (Long.valueOf(user.getUserId()).equals(itme.getLoginId())) {
						itme.setUsername(user.getUsername());
					}
				});
			});
		}
		return R.ok(page.setRecords(list));
	}

	@Override
	public Map uploadFile(MultipartFile file) {
		R upload = fileService.upload(file);
		Map<String, String> resultMap = (Map<String, String>) upload.getData();
		String fileName = ossBaseHost + resultMap.get("fileName");
		log.info("上传文件地址为：{}", fileName);
		resultMap.put("fileName", fileName);
		return resultMap;
	}

	@Override
	public IPage<PinPaiGuanVo> opPage(Page page, CnBrand cnBrand) {
		IPage<PinPaiGuanVo> vo = cnBrandMapper.opPpgId(page, cnBrand);
		vo.getRecords().parallelStream().collect(Collectors.toList()).forEach(o -> BeanUtil.copyProperties(this.pinPaiGuan(o.getBrandId()), o, new CopyOptions().ignoreNullValue()));
		return vo;
	}

	private final CnCouponLogMapper cnCouponLogMapper;


	/**
	 * 品牌馆详情
	 *
	 * @param req
	 * @return
	 */
	@Override
	public PpgDetailResp ppgDetail(PpgDetailReq req) {
		//登录人
		Long loginId = SecurityUtils.getPersonId();
		List<Long> cnCouponLogList = cnCouponLogMapper.selectList(Wrappers.lambdaQuery(CnCouponLog.class)
				.eq(CnCouponLog::getRecipientId, loginId)
				.eq(CnCouponLog::getStatus, 0))
				.stream().map(CnCouponLog::getCouponId).collect(Collectors.toList());

		PpgDetailResp resp = cnBrandMapper.brandAndLabelById(req.getId());

		List<CnShop> shopList = cnShopMapper.selectList(Wrappers.lambdaQuery(CnShop.class).eq(CnShop::getBrandId, req.getId()).eq(CnShop::getDisplay, 0));
		resp.setShopSize(shopList.size());
		CnCare cnCare = cnCareMapper.selectOne(Wrappers.lambdaQuery(CnCare.class)
				.eq(CnCare::getTgtId, req.getId()).eq(CnCare::getPerId, loginId).eq(CnCare::getType, 0));
		resp.setCareFlag(cnCare != null ? "0" : "1");

		resp = this.setCouponVo_V2_FX(resp, req, cnCouponLogList);
		//分销“赚”字
		resp.setFxFlag(fxConfBrandPersonService.fxFlag(req.getId()));

		//足迹
		CnPerson cnPerson = new CnPerson();
		cnPerson.setId(loginId);
		cnPerson = cnPerson.selectById();
		//有手机号才登陆
		if (null != cnPerson.getPhone()) {
			CnFootPrint temp = cnFootPrintMapper.selectOne(Wrappers.lambdaQuery(CnFootPrint.class)
					.eq(CnFootPrint::getType, 0).eq(CnFootPrint::getPerId, loginId).eq(CnFootPrint::getTatId, req.getId()));
			if (temp == null) {
				CnFootPrint cnFootPrint = new CnFootPrint();
				cnFootPrint.setType(0);
				cnFootPrint.setPerId(loginId);
				cnFootPrint.setTatId(req.getId());
				cnFootPrint.setCreateTime(LocalDateTime.now());
				cnFootPrint.setCreateUser(loginId);
//				cnFootPrintMapper.insert(cnFootPrint);
				cnFootPrintMapper.replaceInto(cnFootPrint);
			} else {
				temp.setUpdateTime(LocalDateTime.now());
				temp.setUpdateUser(loginId);
				cnFootPrintMapper.updateById(temp);
			}
		}
		return resp;
	}

	private PpgDetailResp setCouponVo_V2_FX(PpgDetailResp resp, PpgDetailReq req, List<Long> logList) {
		//品牌下所有优惠券
		List<CnCouponTemplateVo> all = new ArrayList<>();
		//通用券
		List<CnCoupon> tyCoupon = cnCouponService.list(Wrappers.lambdaQuery(CnCoupon.class)
				.eq(CnCoupon::getBrandId, req.getId()).eq(CnCoupon::getType, 0)//通用券
				.eq(CnCoupon::getStatus, 0).orderByDesc(CnCoupon::getCreateTime));
		List<CnShopSimpleVo> simpleVoList = cnCouShopService.findShopSimpleVoByBrandId(req.getId());
		List<CnCouponTemplateVo> tyCouponVoList = tyCoupon.stream().map(o -> {
			CnCouponTemplateVo tyCouponVo = new CnCouponTemplateVo();
			BeanUtil.copyProperties(o, tyCouponVo);
			tyCouponVo.setUseFlag(logList.contains(o.getId()) ? 1 : 0);
			tyCouponVo.setShopSimpleVo(simpleVoList);
			return tyCouponVo;
		}).collect(Collectors.toList());


		List<CnCoupon> mdCoupons = new ArrayList<>();

		List<CnShopSimpleVo> distanceSimpleVos = distanceSimpleVos = cnShopMapper.distanceShopByBranbdId(req);//有距离的门店
		//获取门店券
		if (req.getLatitude() != null) {
			List<Long> shopIds = distanceSimpleVos.stream().map(CnShopSimpleVo::getId).collect(Collectors.toList());//门店id
			if (distanceSimpleVos.size() > 0) {
				List<Long> couShopList = cnCouShopService.list(Wrappers.lambdaQuery(CnCouShop.class).select(CnCouShop::getCouId).in(CnCouShop::getShopId, shopIds).groupBy(CnCouShop::getCouId)).stream().map(o -> o.getCouId()).collect(Collectors.toList());
				if (couShopList.size() > 0)
					mdCoupons = cnCouponService.list(Wrappers.lambdaQuery(CnCoupon.class).in(CnCoupon::getId, couShopList).eq(CnCoupon::getStatus, 0));
			}
		} else {
			//根据创建时间排序
			mdCoupons = cnCouponService.list(Wrappers.lambdaQuery(CnCoupon.class).in(CnCoupon::getBrandId, req.getId()).eq(CnCoupon::getStatus, 0).in(CnCoupon::getType, 1, 2).orderByDesc(CnCoupon::getCreateTime));
		}
		//list根据id转map,根据id拿距离
		Map<Long, Long> tempShopDistanceMap = distanceSimpleVos.stream().collect(Collectors.toMap(CnShopSimpleVo::getId, o -> o.getDistance()));
		List<CnCouponTemplateVo> mdCouList = mdCoupons.stream().map(o -> {
			List<CnShopSimpleVo> shopSimpleVoList = cnCouShopService.findShop4CouponListByCouponId(o.getId()).stream().map(oo -> {
				oo.setDistance(tempShopDistanceMap.getOrDefault(oo.getId(), Long.valueOf(0)));
				return oo;
			}).collect(Collectors.toList())
					.stream().sorted(Comparator.comparing(CnShopSimpleVo::getDistance)).collect(Collectors.toList());//距离升序排序
			CnCouponTemplateVo vo = new CnCouponTemplateVo();
			BeanUtil.copyProperties(o, vo);
			vo.setLowMoney(o.getLowMoney());
			vo.setShopSimpleVo(shopSimpleVoList);
			vo.setUseFlag(logList.contains(o.getId()) ? 1 : 0);
			vo.setType(1);//都改成1多门店券，用作排序通用是0
			return vo;
		}).collect(Collectors.toList());
		//有距离则根据距离
		if (req.getLatitude() != null)
			mdCouList.stream().sorted(Comparator.comparing(ooo -> ooo.getShopSimpleVo().get(0).getDistance())).collect(Collectors.toList());
		all.addAll(tyCouponVoList);
		all.addAll(mdCouList);
		all = all.stream().sorted(Comparator.comparing(CnCouponTemplateVo::getUseFlag)).collect(Collectors.toList());
		resp.setCouponList(all);
		return resp;
	}


	private PpgDetailResp setCouponVo(PpgDetailResp resp, PpgDetailReq req, List<Long> cnCouponLogList) {
		//通用券
		List<CnCoupon> tyCoupon = cnCouponService.list(Wrappers.lambdaQuery(CnCoupon.class)
				.eq(CnCoupon::getBrandId, req.getId())
				.eq(CnCoupon::getType, 0)//通用券
				.eq(CnCoupon::getStatus, 0)//上架s
				.orderByDesc(CnCoupon::getCreateTime));
		List<TyCouponVo> tyCouponVoList = new ArrayList<>();

		tyCoupon.stream().forEach(o -> {
			TyCouponVo tyCouponVo = new TyCouponVo();
			BeanUtil.copyProperties(o, tyCouponVo);
			tyCouponVo.setUseFlag(cnCouponLogList.contains(o.getId()) ? 1 : 0);
			tyCouponVoList.add(tyCouponVo);
		});


		List<CnShopSimpleVo> simpleVoList = cnCouShopService.findShopSimpleVoByBrandId(req.getId());
		/**
		 *  //先根据状态升序排序
		 * 	 //根据时间降序排序
		 */
		List<TyCouponVo> tyList = tyCouponVoList.stream()
				.sorted(Comparator.comparing(TyCouponVo::getUseFlag).reversed()
						.thenComparing(CnCoupon::getCreateTime).reversed())
				.collect(Collectors.toList());
		tyList.stream().forEach(o -> o.setShopSimpleVo(simpleVoList));
		resp.setTyCoupon(tyList);
		//门店券
		List<CnCoupon> shopCoulist = cnCouponService.list(Wrappers.lambdaQuery(CnCoupon.class)
				.eq(CnCoupon::getBrandId, req.getId()).ne(CnCoupon::getType, 0)//非通用券
				.eq(CnCoupon::getStatus, 0)//上架
				.orderByDesc(CnCoupon::getReductionMoney));//最大金额倒叙
//				.stream().filter(o->cnCouponLogList.contains(o.getId())!=true).collect(Collectors.toList());


		List<CnCouponTemplateVo> shopCoulistTemp = new ArrayList<>();
		shopCoulist.parallelStream().collect(Collectors.toList()).forEach(oo -> {
			CnCouponTemplateVo vo = new CnCouponTemplateVo();
			List<CnShopSimpleVo> simpleVoList1 = cnCouShopService.findShop4CouponListByCouponId(oo.getId());
			//适用门店
			BeanUtil.copyProperties(oo, vo);
			vo.setLowMoney(oo.getLowMoney());
			vo.setShopSimpleVo(simpleVoList1);
			vo.setUseFlag(cnCouponLogList.contains(oo.getId()) ? 1 : 0);
			shopCoulistTemp.add(vo);
		});

		/**
		 *  //先根据状态升序排序
		 * 	 //根据时间降序排序
		 */
		List<CnCouponTemplateVo> shopVo = shopCoulistTemp.stream()
				.sorted(Comparator.comparing(CnCouponTemplateVo::getUseFlag).reversed()
						.thenComparing(CnCouponTemplateVo::getCreateTime).reversed())
				.collect(Collectors.toList());
		resp.setMdCoupon(shopVo);
		return resp;
	}


	@Override
	public List<CnCouponVo> findCouponByShopId(Long brandId, String couponName) {
		return this.baseMapper.findCouponByShopId(brandId, couponName);
	}

	@Override
	public Long queryByUserId(Long userId) {
		return this.baseMapper.queryByUserId(userId);
	}


	private final CnFootPrintMapper cnFootPrintMapper;

	/**
	 * 品牌馆优惠券
	 *
	 * @param brandId
	 * @return
	 */
	@Override
	/**
	 * 品牌馆列表
	 * 用户创建完品牌馆
	 * 展示形式未：品牌馆外显图+底部俩个优惠劵
	 *
	 * 优惠劵来源为：该品牌下的通用劵与门店劵
	 * 展示规则：
	 * 1、优先展示未领取抵扣金额最大的俩个通用劵
	 * 2、未领取通用劵不足俩个，获取门店劵抵扣金额最大的自动往前补位
	 * 3、门店劵领劵完后，展示最早已领取的2个优惠劵，优惠劵状态为已领取
	 * 4、品牌馆底下没有优惠劵，则不展示
	 */
	public PinPaiGuanVo pinPaiGuan(Long brandId) {
		int num = 2;
		PinPaiGuanVo o = this.pinPaiGuanPinPai(brandId);
		if (o == null) {
			o =new PinPaiGuanVo();
		}

		//我领取的券
		List<CnCouponLog> logList = cnCouponLogMapper.selectList(Wrappers.lambdaQuery(CnCouponLog.class)
				.eq(CnCouponLog::getRecipientId, SecurityUtils.getPersonId())
				.eq(CnCouponLog::getStatus, 0)
				.eq(CnCouponLog::getBrandId, brandId)//同品牌下的优惠券
				.orderByAsc(CnCouponLog::getReceiveTime)//领取时间升序
		);//待使用

		List<Long> logIdList = logList.stream().map(CnCouponLog::getCouponId).collect(Collectors.toList());

		List<CnCoupon> tempList = cnCouponService.list(Wrappers.lambdaQuery(CnCoupon.class)
				.eq(CnCoupon::getBrandId, brandId).eq(CnCoupon::getType, 0)//通用券
				.eq(CnCoupon::getStatus, 0)//上架
				.orderByDesc(CnCoupon::getReductionMoney))//最大金额倒叙
				.stream().filter(oo -> logIdList.contains(oo.getId()) != true).collect(Collectors.toList());//过滤掉我已经领取的

		List<CnCoupon> list = tempList.size() >= num ? tempList.subList(0, num) : tempList;//取前num个

		List<CnCouponTemplateVo> templateVoList = new ArrayList<>();
		list.parallelStream().collect(Collectors.toList()).forEach(oo -> {
			CnCouponTemplateVo vo = new CnCouponTemplateVo();
			BeanUtil.copyProperties(oo, vo);
			vo.setLowMoney(oo.getLowMoney());
			templateVoList.add(vo);
		});

		List<CnShopSimpleVo> simpleList = cnCouShopService.findShopSimpleVoByBrandId(brandId);
		templateVoList.stream().forEach(oo -> oo.setShopSimpleVo(simpleList));

		o.setList(templateVoList);
		if (list.size() == num) {
			return o;
		}

		//小于十个就去取门店券的最大金额
		List<CnCoupon> tempCouList = cnCouponService.list(Wrappers.lambdaQuery(CnCoupon.class)
				.eq(CnCoupon::getBrandId, o.getBrandId()).ne(CnCoupon::getType, 0)//非通用券
				.eq(CnCoupon::getStatus, 0)//上架
				.orderByDesc(CnCoupon::getReductionMoney))//最大金额倒叙
				.stream().filter(oo -> logIdList.contains(oo.getId()) != true).collect(Collectors.toList());//过滤已领取的

		List<CnCoupon> shopCoulist = tempCouList.size() >= num - list.size() ? tempCouList.subList(0, num - list.size()) : tempCouList;//取前num个

		if (shopCoulist.size() < num) {//未领取的券的数量小于num，则使用已经领取的券正序，取num -shopCoulist.size() 个已领取的券
			Integer subNum = num - shopCoulist.size();//需要被截取的数量
			List<CnCouponLog> subLogList = logList.size() > subNum ? logList.subList(0, subNum) : logList;
			List<Long> subCouponIds = subLogList.stream().map(CnCouponLog::getCouponId).collect(Collectors.toList());
			if (subCouponIds.size() > 0) {
				List<CnCoupon> subCouponList = cnCouponService.listByIds(subCouponIds).stream().filter(oo -> 0 == oo.getStatus()).collect(Collectors.toList());
				shopCoulist.addAll(subCouponList);
			}
		}

		PinPaiGuanVo finalO = o;
		shopCoulist.parallelStream().collect(Collectors.toList()).forEach(oo -> {
			CnCouponTemplateVo vo = new CnCouponTemplateVo();
			List<CnShopSimpleVo> simpleVoList = cnCouShopService.findShop4CouponListByCouponId(oo.getId());
			//适用门店
			BeanUtil.copyProperties(oo, vo);
			vo.setLowMoney(oo.getLowMoney());
			vo.setShopSimpleVo(simpleVoList);
			vo.setUseFlag(logIdList.contains(oo.getId()) ? 1 : 0);
			finalO.getList().add(vo);
		});
		return o;
	}

	/**
	 * 品牌馆品牌头部
	 *
	 * @param brandId
	 * @return
	 */
	@Override
	public PinPaiGuanVo pinPaiGuanPinPai(Long brandId) {
		return cnBrandMapper.pinPaiGuanPinPai(brandId);
	}

	/**
	 * 品牌上下架
	 *
	 * @param cnBrandVo 品牌表
	 * @return
	 */
	@Override
	public R updateByDisplay(CnBrandVo cnBrandVo) throws Exception {
		cnBrandVo.setUpdateUser(SecurityUtils.getUserId());
		cnBrandVo.setUpdateTime(LocalDateTime.now());
		CnBrand cnBrand = BeanUtil.toBean(cnBrandVo, CnBrand.class);
		// 上架
		if (cnBrandVo.getDisplay().equals(0)) {
			CnBrand brand = this.getById(cnBrandVo.getId());
			if (brand.getContractStartTime().isAfter(LocalDateTime.now()) || brand.getContractEndTime().isBefore(LocalDateTime.now())) {
				return R.failed("当前时间不在该品牌合作时间内，不能上架");
			}
			cnBrand.setOnTime(LocalDateTime.now());
			return R.ok(this.updateById(cnBrand));
			// 下架
		} else {
			cnBrand.setOffTime(LocalDateTime.now());

			return R.ok();
		}
	}

	@Override
	public List<CnBrandLabel> brandAndLabelByIds(List toList) {
		return toList.size()>0?cnBrandMapper.brandAndLabelByIds(toList):new ArrayList<>();
	}

	/**
	 * S-01首页（品牌）分页查询
	 *
	 * @param page           分页
	 * @param homePageSearch 条件
	 * @return
	 */
	@Override
	public IPage<CnBrandVo> getCmsBrandPage(Page page, HomePageSearch homePageSearch) {
		return cnBrandMapper.getCmsBrandPage(page, homePageSearch);
	}
}
